import type { ComputedRef } from 'vue';
import type { BasicTableProps } from '../types/table';
import { ref, unref } from 'vue';
import { ROW_KEY } from '../const';
import { isString, isFunction } from '@/utils/is';

interface Options {
  setSelectedRowKeys: (keys: string[]) => void;
  getSelectRowKeys: () => string[];
  clearSelectedRowKeys: () => void;
  emit: EmitType;
  getAutoCreateKey: ComputedRef<boolean | undefined>;
}

function getKey(
  record: Recordable,
  rowKey: string | ((record: Record<string, any>) => string) | undefined,
  autoCreateKey?: boolean,
) {
  if (!rowKey || autoCreateKey) {
    return record[ROW_KEY];
  }
  if (isString(rowKey)) {
    return record[rowKey];
  }
  if (isFunction(rowKey)) {
    return record[rowKey(record)];
  }
  return null;
}




export function useCustomRow(
  propsRef: ComputedRef<BasicTableProps>,
  getDataSourceRef: ComputedRef<Recordable<any>[]>,
  { setSelectedRowKeys, getSelectRowKeys, getAutoCreateKey, clearSelectedRowKeys, emit }: Options,
) {
  const defaultRowKey = 'id'
  const defaultChildrenColumnName = 'children'

  const defaultCustomRow = (record: Recordable, index: number) => {
    return {
      onClick: (e: Event) => {
        e?.stopPropagation();
        function handleClick() {
          const { rowSelection, rowKey, clickToRowSelect } = unref(propsRef);
          if (!rowSelection || !clickToRowSelect) return;
          const keys = getSelectRowKeys();
          const key = getKey(record, rowKey, unref(getAutoCreateKey));
          if (!key) return;

          const isCheckbox = rowSelection.type === 'checkbox';
          if (isCheckbox) {
            // 找到tr
            const tr: HTMLElement = (e as MouseEvent)
              .composedPath?.()
              .find((dom: HTMLElement) => dom.tagName === 'TR') as HTMLElement;
            if (!tr) return;
            // 找到Checkbox，检查是否为disabled
            const checkBox = tr.querySelector('input[type=checkbox]');
            if (!checkBox || checkBox.hasAttribute('disabled')) return;
            if (!keys?.includes(key)) {
              setSelectedRowKeys([...keys, key]);
              return;
            }
            const keyIndex = keys.findIndex((item) => item === key);
            keys.splice(keyIndex, 1);
            setSelectedRowKeys(keys);
            return;
          }

          const isRadio = rowSelection.type === 'radio';
          if (isRadio) {
            if (!keys.includes(key)) {
              if (keys.length) {
                clearSelectedRowKeys();
              }
              setSelectedRowKeys([key]);
              return;
            }
            clearSelectedRowKeys();
          }
        }
        handleClick();
        emit('row-click', record, index, e);
      },
      onDblclick: (event: Event) => {
        emit('row-dbClick', record, index, event);
      },
      onContextmenu: (event: Event) => {
        emit('row-contextmenu', record, index, event);
      },
      onMouseenter: (event: Event) => {
        emit('row-mouseenter', record, index, event);
      },
      onMouseleave: (event: Event) => {
        emit('row-mouseleave', record, index, event);
      },
    };
  }

  function getRecordIndex(item: Recordable, indexType: 'me' | 'first' | 'second' = 'me'): number {
    const childrenColumnName = propsRef.value.childrenColumnName || defaultChildrenColumnName
    const rowKey = (propsRef.value.rowKey as string) || defaultRowKey
    const dataSource = getDataSourceRef.value
    if (item.level === 1 || !Object.hasOwn(item, childrenColumnName)) return dataSource.findIndex((v) => v[rowKey] === item[rowKey]);
    if (item.level === 2) {
      let firstLevelIndex = dataSource.findIndex((v) => v[rowKey] === item.parentId);
      if (indexType === 'first') return firstLevelIndex;
      return dataSource[firstLevelIndex][childrenColumnName].findIndex((v) => v[rowKey] === item[rowKey]);
    } else {
      for (let index = 0; index < dataSource.length; index++) {
        const sIndex = dataSource[index][childrenColumnName].findIndex((s) => s[rowKey] === item.parentId);
        if (sIndex !== -1) {
          let sItem = dataSource[index][childrenColumnName][sIndex];
          if (indexType === 'first') return index;
          if (indexType === 'second') return sIndex;
          return sItem[childrenColumnName].findIndex((v) => v[rowKey] === item[rowKey]);
        }
      }
    }

    return -1
  }

  const sourceItem = ref<{ index: number; obj: Recordable }>(); // 源目标数据序号
  const rowDragCustomRow = (record: Recordable) => {
    return {
      props: {
        // draggable: 'true'
      },
      style: {
        cursor: 'pointer',
      },
      // 鼠标移入
      onMouseenter: (event) => {
        // 兼容IE
        var ev = event || window.event;
        ev.target.draggable = true; // 让你要拖动的行可以拖动，默认不可以
      },
      // 开始拖拽
      onDragstart: (event) => {
        // 兼容IE
        var ev = event || window.event;
        // 阻止冒泡
        ev.stopPropagation();
        // 得到源目标数据序号
        sourceItem.value = {
          index: getRecordIndex(record),
          obj: record,
        };
      },
      // 拖动元素经过的元素
      onDragover: (event) => {
        // 兼容 IE
        var ev = event || window.event;
        // 阻止默认行为
        ev.preventDefault();
      },
      // 鼠标松开
      onDrop: async (event) => {
        // 兼容IE
        var ev = event || window.event;
        // 阻止冒泡
        ev.stopPropagation();
        if (!sourceItem.value) return;
        let dataSource = getDataSourceRef.value
        let data: Recordable<any>[];
        const { index: sourceIndex, obj } = sourceItem.value;
        /** 判断数据是否在同层, 是否在自身 */
        if (obj.parentId !== record.parentId || obj.id === record.id) return;
        const targetIndex = getRecordIndex(record)
        const childrenColumnName = propsRef.value.childrenColumnName || defaultChildrenColumnName
        const beforeRowDragChange = propsRef.value.beforeRowDragChange

        /** 判断是否是一级数据, 一级数据直接切换 */
        if (obj.level === 1 || !Object.hasOwn(obj, childrenColumnName)) {
          data = dataSource
        } else {
          let firstLevelIndex = getRecordIndex(obj, 'first')
          /** 判断数据在第几级 */
          if (obj.level === 2) {
            data = dataSource[firstLevelIndex][childrenColumnName];
          } else {
            let secondaryIndex = getRecordIndex(obj, 'second')
            data = dataSource[firstLevelIndex][childrenColumnName][secondaryIndex][childrenColumnName];
          }
        }

        if (isFunction(beforeRowDragChange)) {
          const res = await beforeRowDragChange(data[sourceIndex], data[targetIndex]);
          if (!res) return
        }

        [data[sourceIndex], data[targetIndex]] = [data[targetIndex], data[sourceIndex]];
      },
    };
  }

  const customRow = (record: Recordable, index: number) => {
    if (propsRef.value.canRowDrag) {
      return rowDragCustomRow(record)
    } else {
      return defaultCustomRow(record, index)
    }
  };

  return {
    customRow,
  };
}
